package edu.controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.primefaces.model.DualListModel;

import edu.terapia.model.Persona;
import edu.terapia.model.Servicio;
import edu.terapia.model.TipoPersona;
import edu.util.HbnUtil;

@ManagedBean(name="terapeutaBean")
@SessionScoped
public class TerapeutaBean implements Serializable {

	public Persona persona;
	public List<Persona> perList = null;
	public List<TipoPersona> tipoPersonas = null;
	public TipoPersona tipoPersona = null;
	
	public Servicio servicio;
	public DualListModel<Servicio> servicios;
	
	public static final int TIPO_PERSONA_TERAPEUTA_ID = 100;
	
	public Persona getPersona() {
		return persona;
	}
	public void setPersona(Persona persona) {
		this.persona = persona;
	}
	
	public TipoPersona getTipoPersona() {
		return tipoPersona;
	}
	public void setTipoPersona(TipoPersona tipoPersona) {
		this.tipoPersona = tipoPersona;
	}

	public List<Persona> getPerList() {
		return perList;
	}
	
	public List<TipoPersona> getTipoPersonas() {
		return tipoPersonas;
	}
	
	public Servicio getServicio() {
		return servicio;
	}
	public void setServicio(Servicio servicio) {
		this.servicio = servicio;
	}
	public DualListModel<Servicio> getServicios() {
		return servicios;
	}
	public void setServicios(DualListModel<Servicio> servicios) {
		this.servicios = servicios;
	}
	
	@SuppressWarnings("unchecked")
	public TerapeutaBean() {
		persona = new Persona();
		tipoPersona = new TipoPersona();
		servicio = new Servicio();
		servicios = new DualListModel<Servicio>();
		
		SessionFactory s =  HbnUtil.getSessionFactory();
		Transaction t = s.getCurrentSession().beginTransaction();
		perList = getCustomTerapeutaList(s);
		tipoPersonas = getCustomTiposTerapeuta(s);
		
		List<Servicio> source = s.getCurrentSession().createSQLQuery("select s.* from servicios s where s.status = 'activo' ")
				.addEntity(Servicio.class)
				.list();
		List<Servicio> target = new ArrayList<Servicio>();
		
		servicios.setSource(source); // s.getCurrentSession().createCriteria(Servicio.class).list();
		servicios.setTarget(target); 
		t.commit();
		s.close();
	}
	
	public String save() {
		SessionFactory s =  HbnUtil.getSessionFactory();
		Transaction t = s.getCurrentSession().beginTransaction();
		
		tipoPersona = getCustomTerapeuta(s);
		persona.setTipoPersona(tipoPersona);

		List<Servicio> temp = servicios.getTarget();

		Integer next =  (Integer) s.getCurrentSession().save(persona);
		
		for (Iterator<Servicio> iterator = temp.iterator(); iterator.hasNext();) {
			Servicio servicio = iterator.next();
			s.getCurrentSession()
			.createSQLQuery("insert into personas_servicios(servicios_id, personas_id) values(:servicio, :persona) ")
			.setParameter("servicio", servicio.getId())
			.setParameter("persona", next.intValue())
			.executeUpdate();
		}
		
		perList = getCustomTerapeutaList(s);
		t.commit();
		s.close();
		return "terapeuta?faces-redirect=true";
	}
	
	public String update() {
		persona.setServicios(servicios.getTarget());
		
		persona.setTipoPersona(tipoPersona);
		SessionFactory s =  HbnUtil.getSessionFactory();
		Transaction t = s.getCurrentSession().beginTransaction();
		
		List<Servicio> temp = servicios.getTarget();
		
		int c = s.getCurrentSession()
				.createSQLQuery("delete from personas_servicios where personas_id = :persona ")
				.setParameter("persona", persona.getId())
				.executeUpdate();
		
		for (Iterator<Servicio> iterator = temp.iterator(); iterator.hasNext();) {
			Servicio servicio = iterator.next();
			
			s.getCurrentSession()
			.createSQLQuery("insert into personas_servicios(servicios_id, personas_id) values(:servicio, :persona) ")
			.setParameter("servicio", servicio.getId())
			.setParameter("persona", persona.getId())
			.executeUpdate();
		}
		
		s.getCurrentSession().update(persona);
		perList = getCustomTerapeutaList(s);
		t.commit();
		s.close();
		return "terapeuta?faces-redirect=true";
	}
	
	@SuppressWarnings("unchecked")
	public String edit(Persona persona) {
		SessionFactory s =  HbnUtil.getSessionFactory();
		Transaction t = s.getCurrentSession().beginTransaction();
		
		this.persona = persona;
		this.tipoPersona = persona.getTipoPersona();
//		this.servicio = persona.getServicios().get(0);//TODO temporal
		
		List<Servicio> source = s.getCurrentSession().createSQLQuery("select s1.* from servicios s1 "
				+ "where id not in ( select s.id from servicios s, personas_servicios ps, persona p "
				+ "where ps.personas_id =  p.id and ps.servicios_id = s.id and ps.personas_id = :persona_id ) and s1.status = 'activo' ")
				.addEntity(Servicio.class)
				.setParameter("persona_id", persona.getId())
				.list();
		List<Servicio> target = s.getCurrentSession().createSQLQuery("select s.* "
				+ "from servicios s, personas_servicios ps, persona p "
				+ "where ps.personas_id =  p.id  and ps.servicios_id = s.id and ps.personas_id = :persona_id and s.status = 'activo' ")
				.addEntity(Servicio.class)
				.setParameter("persona_id", persona.getId())
				.list();
		
		servicios.setSource(source); // s.getCurrentSession().createCriteria(Servicio.class).list();
		servicios.setTarget(target);
		
		t.commit();
		s.close();
		
		return "update_terapeuta?faces-redirect=true";
	}
	
	public String delete(Persona persona) {
		this.persona = persona;
		
		persona.setServicios(servicios.getTarget());
		
		persona.setTipoPersona(tipoPersona);
		SessionFactory s =  HbnUtil.getSessionFactory();
		Transaction t = s.getCurrentSession().beginTransaction();
		s.getCurrentSession().delete(persona);
		perList = getCustomTerapeutaList(s);
		t.commit();
		s.close();
		return "terapeuta?faces-redirect=true";
	}
	
	
	@SuppressWarnings("unchecked")
	public void clear() {
		persona = new Persona();
		tipoPersona = new TipoPersona();
		servicio = new Servicio();
		
		SessionFactory s =  HbnUtil.getSessionFactory();
		Transaction t = s.getCurrentSession().beginTransaction();
		
		List<Servicio> source = s.getCurrentSession().createSQLQuery("select s.* from servicios s where s.status = 'activo'")
				.addEntity(Servicio.class)
				.list();
		List<Servicio> target = new ArrayList<Servicio>();
		
		servicios.setSource(source); // s.getCurrentSession().createCriteria(Servicio.class).list();
		servicios.setTarget(target); 
		t.commit();
		s.close();
	}
	
	@SuppressWarnings("unchecked")
	private List<Persona> getCustomTerapeutaList(SessionFactory s) {
		return s.getCurrentSession()
				.createSQLQuery("select p.* from persona p where p.tipo_persona_id = :tipo")
				.addEntity(Persona.class)
				.setParameter("tipo", TIPO_PERSONA_TERAPEUTA_ID)
				.list();
	}
	
	private List<TipoPersona> getCustomTiposTerapeuta(SessionFactory s) {
		return (List<TipoPersona>) s.getCurrentSession()
				.createCriteria(TipoPersona.class)
				.add(Restrictions.eq("id", TIPO_PERSONA_TERAPEUTA_ID)).list();
	}
	
	private TipoPersona getCustomTerapeuta(SessionFactory s) {
		return (TipoPersona) s.getCurrentSession()
				.createCriteria(TipoPersona.class)
				.add(Restrictions.eq("id", TIPO_PERSONA_TERAPEUTA_ID)).list().get(0);
	}

}
